import asyncio
import os
import tempfile
from typing import Dict, Any, Optional, List
from urllib.parse import urlparse, parse_qs
import yt_dlp
from datetime import datetime

from config.logging_config import ProjectLoggers
from utils.file_helper import FileHelper

logger = ProjectLoggers.get_service_logger()

class InstagramDownloaderService:
    """Instagram视频下载服务"""
    
    def __init__(self):
        self.temp_dir = tempfile.gettempdir()
        
    def _get_media_id_from_url(self, url: str) -> Optional[str]:
        """从Instagram URL中提取媒体ID"""
        try:
            parsed_url = urlparse(url)
            
            # 处理不同类型的Instagram URL
            if 'instagram.com' in parsed_url.netloc:
                path_parts = parsed_url.path.split('/')
                
                if '/p/' in parsed_url.path:
                    # Instagram帖子: https://www.instagram.com/p/POST_ID/
                    post_index = path_parts.index('p')
                    if post_index + 1 < len(path_parts):
                        return path_parts[post_index + 1]
                elif '/reel/' in parsed_url.path:
                    # Instagram Reels: https://www.instagram.com/reel/REEL_ID/
                    reel_index = path_parts.index('reel')
                    if reel_index + 1 < len(path_parts):
                        return path_parts[reel_index + 1]
                elif '/tv/' in parsed_url.path:
                    # Instagram TV: https://www.instagram.com/tv/TV_ID/
                    tv_index = path_parts.index('tv')
                    if tv_index + 1 < len(path_parts):
                        return path_parts[tv_index + 1]
                elif '/stories/' in parsed_url.path:
                    # Instagram Stories: https://www.instagram.com/stories/username/STORY_ID/
                    stories_index = path_parts.index('stories')
                    if stories_index + 2 < len(path_parts):
                        return path_parts[stories_index + 2]
                        
            return None
        except Exception as e:
            logger.error(f"解析Instagram URL失败: {str(e)}")
            return None
    
    def _is_instagram_url(self, url: str) -> bool:
        """检查是否为有效的Instagram URL"""
        try:
            parsed_url = urlparse(url)
            instagram_domains = ['instagram.com', 'www.instagram.com', 'm.instagram.com']
            
            if any(domain in parsed_url.netloc for domain in instagram_domains):
                # 检查是否包含媒体相关路径
                media_patterns = ['/p/', '/reel/', '/tv/', '/stories/']
                return any(pattern in parsed_url.path for pattern in media_patterns)
            
            return False
        except:
            return False
    
    async def get_media_info(self, instagram_url: str) -> Dict[str, Any]:
        """获取Instagram媒体信息"""
        try:
            if not self._is_instagram_url(instagram_url):
                return {
                    "success": False,
                    "error": "不是有效的Instagram链接"
                }
            
            # 配置yt-dlp选项
            ydl_opts = {
                'quiet': True,
                'no_warnings': True,
                'extractaudio': False,
                'format': 'best',
                # Instagram需要的特殊配置
                'cookiefile': None,  # 可以添加cookie文件路径
                'user_agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.3 Mobile/15E148 Safari/604.1',
                # Instagram特定选项
                'extractor_args': {
                    'instagram': {
                        'comment_count': [0],  # 不获取评论
                    }
                }
            }
            
            # 异步执行媒体信息获取
            def _extract_info():
                with yt_dlp.YoutubeDL(ydl_opts) as ydl:
                    return ydl.extract_info(instagram_url, download=False)
            
            loop = asyncio.get_event_loop()
            info = await loop.run_in_executor(None, _extract_info)
            
            if not info:
                return {
                    "success": False,
                    "error": "无法获取媒体信息，可能是私有内容或需要登录"
                }
            
            # 提取有用的信息
            media_info = {
                "media_id": info.get('id'),
                "title": info.get('title') or info.get('description', '').split('\n')[0][:100],
                "uploader": info.get('uploader'),
                "uploader_id": info.get('uploader_id'),
                "duration": info.get('duration'),
                "view_count": info.get('view_count'),
                "like_count": info.get('like_count'),
                "comment_count": info.get('comment_count'),
                "upload_date": info.get('upload_date'),
                "description": info.get('description', '')[:500] + '...' if info.get('description', '') else '',
                "thumbnail": info.get('thumbnail'),
                "webpage_url": info.get('webpage_url'),
                "is_video": True if info.get('vcodec') != 'none' else False,
                "width": info.get('width'),
                "height": info.get('height'),
                "formats": []
            }
            
            # 获取可用格式
            formats = info.get('formats', [])
            for fmt in formats:
                if fmt.get('vcodec') != 'none':  # 只要包含视频的格式
                    format_info = {
                        "format_id": fmt.get('format_id'),
                        "ext": fmt.get('ext'),
                        "resolution": fmt.get('resolution') or f"{fmt.get('width', 'unknown')}x{fmt.get('height', 'unknown')}",
                        "filesize": fmt.get('filesize'),
                        "filesize_approx": fmt.get('filesize_approx'),
                        "url": fmt.get('url'),
                        "quality": fmt.get('quality'),
                        "format_note": fmt.get('format_note'),
                        "fps": fmt.get('fps'),
                        "vcodec": fmt.get('vcodec'),
                        "acodec": fmt.get('acodec'),
                        "width": fmt.get('width'),
                        "height": fmt.get('height')
                    }
                    media_info["formats"].append(format_info)
            
            # 按质量排序
            media_info["formats"] = sorted(
                media_info["formats"], 
                key=lambda x: (x.get('quality') or 0), 
                reverse=True
            )
            
            logger.info(f"成功获取Instagram媒体信息: {media_info['title']}")
            
            return {
                "success": True,
                "data": media_info
            }
            
        except Exception as e:
            logger.error(f"获取Instagram媒体信息失败: {str(e)}")
            return {
                "success": False,
                "error": f"获取媒体信息失败: {str(e)}"
            }
    
    async def get_download_urls(self, instagram_url: str, quality: str = "best") -> Dict[str, Any]:
        """获取Instagram媒体下载链接"""
        try:
            if not self._is_instagram_url(instagram_url):
                return {
                    "success": False,
                    "error": "不是有效的Instagram链接"
                }
            
            # 根据质量设置格式选择器
            quality_map = {
                "1080p": "best[height<=1080]",
                "720p": "best[height<=720]", 
                "480p": "best[height<=480]",
                "360p": "best[height<=360]",
                "best": "best",
                "worst": "worst"
            }
            
            format_selector = quality_map.get(quality, "best")
            
            ydl_opts = {
                'quiet': True,
                'no_warnings': True,
                'format': format_selector,
                'user_agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.3 Mobile/15E148 Safari/604.1',
                'extractor_args': {
                    'instagram': {
                        'comment_count': [0],
                    }
                }
            }
            
            def _extract_info():
                with yt_dlp.YoutubeDL(ydl_opts) as ydl:
                    return ydl.extract_info(instagram_url, download=False)
            
            loop = asyncio.get_event_loop()
            info = await loop.run_in_executor(None, _extract_info)
            
            if not info:
                return {
                    "success": False,
                    "error": "无法获取下载链接，可能是私有内容或需要登录"
                }
            
            # 获取最佳格式的下载链接
            download_url = info.get('url')
            if not download_url:
                return {
                    "success": False,
                    "error": "无法获取有效的下载链接"
                }
            
            result = {
                "media_id": info.get('id'),
                "title": info.get('title') or info.get('description', '').split('\n')[0][:100],
                "uploader": info.get('uploader'),
                "uploader_id": info.get('uploader_id'),
                "download_url": download_url,
                "format": info.get('ext'),
                "resolution": info.get('resolution') or f"{info.get('width', 'unknown')}x{info.get('height', 'unknown')}",
                "width": info.get('width'),
                "height": info.get('height'),
                "filesize": info.get('filesize'),
                "filesize_approx": info.get('filesize_approx'),
                "duration": info.get('duration'),
                "thumbnail": info.get('thumbnail'),
                "fps": info.get('fps'),
                "vcodec": info.get('vcodec'),
                "acodec": info.get('acodec'),
                "webpage_url": info.get('webpage_url'),
                "like_count": info.get('like_count'),
                "view_count": info.get('view_count'),
                "is_video": True if info.get('vcodec') != 'none' else False
            }
            
            logger.info(f"成功获取Instagram下载链接: {result['title']}")
            
            return {
                "success": True,
                "data": result
            }
            
        except Exception as e:
            logger.error(f"获取Instagram下载链接失败: {str(e)}")
            return {
                "success": False,
                "error": f"获取下载链接失败: {str(e)}"
            }
    
    async def get_multiple_quality_urls(self, instagram_url: str) -> Dict[str, Any]:
        """获取多种质量的下载链接"""
        try:
            if not self._is_instagram_url(instagram_url):
                return {
                    "success": False,
                    "error": "不是有效的Instagram链接"
                }
            
            # 首先获取所有格式信息
            info_result = await self.get_media_info(instagram_url)
            if not info_result["success"]:
                return info_result
            
            media_info = info_result["data"]
            formats = media_info.get("formats", [])
            
            if not formats:
                return {
                    "success": False,
                    "error": "没有找到可用的视频格式"
                }
            
            # 组织不同质量的下载链接
            quality_urls = {}
            
            # 按分辨率分组
            resolution_groups = {}
            for fmt in formats:
                resolution = fmt.get('resolution', 'unknown')
                if resolution != 'unknown' and fmt.get('url'):
                    if resolution not in resolution_groups:
                        resolution_groups[resolution] = []
                    resolution_groups[resolution].append(fmt)
            
            # 选择每个分辨率的最佳格式
            for resolution, res_formats in resolution_groups.items():
                # 按质量分数排序，选择最好的
                best_format = sorted(res_formats, key=lambda x: x.get('quality', 0), reverse=True)[0]
                
                quality_urls[resolution] = {
                    "url": best_format.get('url'),
                    "format": best_format.get('ext'),
                    "width": best_format.get('width'),
                    "height": best_format.get('height'),
                    "filesize": best_format.get('filesize'),
                    "filesize_approx": best_format.get('filesize_approx'),
                    "fps": best_format.get('fps'),
                    "vcodec": best_format.get('vcodec'),
                    "acodec": best_format.get('acodec')
                }
            
            result = {
                "media_id": media_info.get('media_id'),
                "title": media_info.get('title'),
                "uploader": media_info.get('uploader'),
                "uploader_id": media_info.get('uploader_id'),
                "duration": media_info.get('duration'),
                "thumbnail": media_info.get('thumbnail'),
                "like_count": media_info.get('like_count'),
                "view_count": media_info.get('view_count'),
                "quality_urls": quality_urls,
                "available_qualities": list(quality_urls.keys()),
                "is_video": media_info.get('is_video')
            }
            
            logger.info(f"成功获取Instagram多质量下载链接: {result['title']}")
            
            return {
                "success": True,
                "data": result
            }
            
        except Exception as e:
            logger.error(f"获取Instagram多质量下载链接失败: {str(e)}")
            return {
                "success": False,
                "error": f"获取多质量下载链接失败: {str(e)}"
            }
    
    async def get_user_media_urls(self, username: str, count: int = 12) -> Dict[str, Any]:
        """获取用户最新媒体链接（可选功能）"""
        try:
            # 构建用户页面URL
            user_url = f"https://www.instagram.com/{username}/"
            
            ydl_opts = {
                'quiet': True,
                'no_warnings': True,
                'extract_flat': True,  # 只提取基本信息，不下载
                'playlist_items': f'1:{count}',  # 限制数量
                'user_agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.3 Mobile/15E148 Safari/604.1',
            }
            
            def _extract_info():
                with yt_dlp.YoutubeDL(ydl_opts) as ydl:
                    return ydl.extract_info(user_url, download=False)
            
            loop = asyncio.get_event_loop()
            info = await loop.run_in_executor(None, _extract_info)
            
            if not info or 'entries' not in info:
                return {
                    "success": False,
                    "error": "无法获取用户媒体，可能是私有账户或不存在"
                }
            
            # 提取媒体信息
            media_list = []
            for entry in info['entries'][:count]:
                if entry:
                    media_info = {
                        "id": entry.get('id'),
                        "title": entry.get('title', ''),
                        "url": entry.get('url'),
                        "thumbnail": entry.get('thumbnail'),
                        "duration": entry.get('duration'),
                        "view_count": entry.get('view_count'),
                    }
                    media_list.append(media_info)
            
            result = {
                "username": username,
                "user_id": info.get('uploader_id'),
                "user_title": info.get('uploader'),
                "media_count": len(media_list),
                "media_list": media_list
            }
            
            logger.info(f"成功获取用户 {username} 的媒体列表")
            
            return {
                "success": True,
                "data": result
            }
            
        except Exception as e:
            logger.error(f"获取用户媒体列表失败: {str(e)}")
            return {
                "success": False,
                "error": f"获取用户媒体列表失败: {str(e)}"
            } 